package api

import (
	"github.com/gin-gonic/gin"
	"github.com/tealeg/xlsx"
	"gorm.io/gorm"
	"io"
	"os"
	"seat-service/model"
	"seat-service/model/dto"
	"seat-service/response"
	service "seat-service/service/impl"
	"seat-service/utils"
	"strconv"
)

var seatService service.SeatService

type SeatApi struct {
}

func (*SeatApi) AddSeat(c *gin.Context) {
	var seatDto dto.AddSeatDto
	err := c.ShouldBindJSON(&seatDto)
	if err != nil {
		response.Fail(c, response.DataInWrongFormat, nil)
		return
	}
	campusId, _ := strconv.Atoi(seatDto.CampusId)
	buildingId, _ := strconv.Atoi(seatDto.BuildingId)
	classroomId, _ := strconv.Atoi(seatDto.ClassroomId)
	seatStatus, _ := strconv.Atoi(seatDto.SeatStatus)
	seat := model.Seat{
		CampusId:    uint(campusId),
		BuildingId:  uint(buildingId),
		ClassroomID: uint(classroomId),
		SeatNumber:  seatDto.SeatNumber,
		SeatStatus:  seatStatus,
	}
	err = seatService.AddSeat(seat)
	if err != nil {
		response.Fail(c, response.DatabaseException, nil)
		return
	}
	response.Success(c, response.CodeSuccess, nil)

}
func (*SeatApi) SeatExel(c *gin.Context) {
	// 生成 Excel 文件
	file := xlsx.NewFile()

	// 添加一个工作表
	sheet, err := file.AddSheet("Sheet1")
	if err != nil {
		response.Fail(c, response.ServerException, nil)
		return
	}

	// 添加标题行
	titles := sheet.AddRow()
	titles.AddCell().SetValue("校区名称(西区/东区/新东区)")
	titles.AddCell().SetValue("教学楼名称")
	titles.AddCell().SetValue("教室名称")
	titles.AddCell().SetValue("座位号")
	titles.AddCell().SetValue("状态(0-正常，1-损坏，2-禁用)")

	// 创建示例数据行
	row := sheet.AddRow()
	row.AddCell().SetValue("西区(模板)")
	row.AddCell().SetValue("一号楼(模板)")
	row.AddCell().SetValue("1103或者合一(模板)")
	row.AddCell().SetValue("A7(模板)")
	row.AddCell().SetValue("0(模板)")

	// 设置 HTTP 头，指定响应类型和附件名
	c.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
	c.Header("Content-Disposition", "attachment; filename=example.xlsx")

	// 使用 xlsx.Write 方法将 Excel 文件直接写入 http.ResponseWriter
	err = file.Write(c.Writer)
	if err != nil {
		response.Fail(c, response.ServerException, nil)
		return
	}
}

func (*SeatApi) BatchAddSeat(c *gin.Context) {
	file, err := c.FormFile("file")
	if err != nil {
		response.Fail(c, response.DataInWrongFormat, nil)
		return
	}
	open, err := file.Open()
	if err != nil {
		response.Fail(c, response.ServerException, nil)
		return
	}
	defer open.Close()

	// 创建一个临时文件
	tempFile, err := os.CreateTemp("", "temp_excel_*.xlsx")
	if err != nil {
		response.Fail(c, response.ServerException, nil)
		return
	}

	// 将上传的文件内容写入临时文件
	_, err = io.Copy(tempFile, open)
	if err != nil {
		response.Fail(c, response.ServerException, nil)
		return
	}
	xlFile, err := xlsx.OpenFile(tempFile.Name())
	if err != nil {
		response.Fail(c, response.ServerException, nil)
		return
	}
	seat := make([]dto.BatchAddSeatDto, 0)
	// 遍历Excel文件中的每个单元格
	for _, sheet := range xlFile.Sheets {
		for i, row := range sheet.Rows {
			if i == 0 {
				continue
			}
			seatSlice := make([]string, 0)
			for _, cell := range row.Cells {
				seatSlice = append(seatSlice, cell.String())
			}
			sea, _ := strconv.Atoi(seatSlice[4])
			seat = append(seat, dto.BatchAddSeatDto{
				Campus:     seatSlice[0],
				Building:   seatSlice[1],
				Classroom:  seatSlice[2],
				SeatNumber: seatSlice[3],
				SeatStatus: sea,
			})
		}
	}
	number, err := seatService.BatchAddSeat(seat)
	if err != nil {
		response.Fail(c, response.DatabaseException, number)
		return
	}
	response.Success(c, response.CodeSuccess, number)

}
func (*SeatApi) DelSeat(c *gin.Context) {
	id := c.Query("id")
	numId, _ := strconv.Atoi(id)
	err := seatService.DelSeat(uint(numId))
	if err != nil {
		response.Fail(c, response.DatabaseException, nil)
		return
	}
	response.Success(c, response.CodeSuccess, nil)

}
func (*SeatApi) BatchDelSeat(c *gin.Context) {
	var seatDto dto.BatchDelDto
	err := c.ShouldBindJSON(&seatDto)
	if err != nil {
		response.Fail(c, response.DataInWrongFormat, nil)
		return
	}

	err = seatService.BatchDelSeat(seatDto)
	if err != nil {
		response.Fail(c, response.DatabaseException, nil)
		return
	}
	response.Success(c, response.CodeSuccess, nil)
}
func (*SeatApi) UpdateSeat(c *gin.Context) {
	var seatDto dto.UpdateSeatDto
	err := c.ShouldBindJSON(&seatDto)
	if err != nil {
		response.Fail(c, response.DataInWrongFormat, nil)
		return
	}
	id, _ := strconv.Atoi(seatDto.Id)
	seatStatus, _ := strconv.Atoi(seatDto.SeatStatus)
	buildingId, _ := strconv.Atoi(seatDto.BuildingId)
	classroomId, _ := strconv.Atoi(seatDto.ClassroomId)
	campusId, _ := strconv.Atoi(seatDto.CampusId)
	seat := model.Seat{
		Model:       gorm.Model{ID: uint(id)},
		CampusId:    uint(campusId),
		BuildingId:  uint(buildingId),
		ClassroomID: uint(classroomId),
		SeatNumber:  seatDto.SeatNumber,
		SeatStatus:  seatStatus,
	}
	err = seatService.UpdateSeat(seat)
	if err != nil {
		response.Fail(c, response.DatabaseException, nil)
		return
	}
	response.Success(c, response.CodeSuccess, nil)
}

func (*SeatApi) QuerySeat(c *gin.Context) {
	page := c.Query("page_no")
	pageSize := c.Query("page_size")
	p, _ := strconv.Atoi(page)
	ps, _ := strconv.Atoi(pageSize)
	res, err := seatService.QuerySeat(p, ps)
	if err != nil {
		response.Fail(c, response.DatabaseException, nil)
		return
	}
	response.Success(c, response.CodeSuccess, res)

}
func (*SeatApi) QuerySeatTabulationCampus(c *gin.Context) {
	campus, err := seatService.QuerySeatTabulationCampus()
	if err != nil {
		response.Fail(c, response.DatabaseException, nil)
		return
	}
	response.Success(c, response.CodeSuccess, campus)
}
func (*SeatApi) QuerySeatTabulationBuilding(c *gin.Context) {
	id := c.Query("id")
	numId, _ := strconv.Atoi(id)
	building, err := seatService.QuerySeatTabulationBuilding(uint(numId))
	if err != nil {
		response.Fail(c, response.DatabaseException, nil)
		return
	}
	response.Success(c, response.CodeSuccess, building)
}
func (*SeatApi) QuerySeatTabulationClassroom(c *gin.Context) {
	id := c.Query("id")
	numId, _ := strconv.Atoi(id)
	classroom, err := seatService.QuerySeatTabulationClassroom(uint(numId))
	if err != nil {
		response.Fail(c, response.DatabaseException, nil)
		return
	}
	response.Success(c, response.CodeSuccess, classroom)
}

func (*SeatApi) QueryConditionSeat(c *gin.Context) {
	campusId := c.Query("campus_id")
	buildingId := c.Query("building_id")
	classroomId := c.Query("classroom_id")
	seatNumber := c.Query("seat_number")
	seatStatus := c.Query("seat_status_id")
	classroomName := c.Query("classroom_name")
	buildingName := c.Query("building_name")
	page := c.Query("page_no")
	pageSize := c.Query("page_size")
	if campusId == "" {
		campusId = "%"
	}
	if buildingId == "" {
		buildingId = "%"
	}
	if classroomId == "" {
		classroomId = "%"
	}
	if seatNumber == "" {
		seatNumber = "%"
	}

	if seatStatus == "" {
		seatStatus = "%"
	}
	if classroomName == "" {
		classroomName = "%"
	}
	if buildingName == "" {
		buildingName = "%"
	}

	p, _ := strconv.Atoi(page)
	ps, _ := strconv.Atoi(pageSize)
	res, err := seatService.QueryConditionSeat(dto.ConditionSeatDto{
		CampusId:      campusId,
		BuildingId:    buildingId,
		ClassroomId:   classroomId,
		SeatNumber:    seatNumber,
		SeatStatus:    seatStatus,
		Page:          p,
		PageSize:      ps,
		ClassroomName: classroomName,
		BuildingName:  buildingName,
	})
	if err != nil {
		response.Fail(c, response.DatabaseException, nil)
		return
	}
	response.Success(c, response.CodeSuccess, res)
}

func (*SeatApi) QueryId(c *gin.Context) {
	id := c.Query("id")
	numId, _ := strconv.Atoi(id)
	res, err := seatService.QueryById(uint(numId))
	if err != nil {
		response.Fail(c, response.DatabaseException, nil)
		return
	}
	response.Success(c, response.CodeSuccess, res)
}

func (*SeatApi) QueryListAll(c *gin.Context) {
	read, err := utils.CacheRedisRead()
	if err != nil {
		response.Fail(c, response.DatabaseException, nil)
		return
	}
	response.Success(c, response.CodeSuccess, read)

}
